var yjxRedisManager = require('./yjxRedisManager');
var YjxUniItemsModel = require('../../../../../common/yjxMysql/mapping/YjxUniItemsModel');
var CONFIG = require('../../../../../common/config');
var moment = require('moment');
var async = require('async');
var redisManager = require('../../util/redisManager');
// 分词模块, 加载搜索宦存时使用
var Segment = require('node-segment').Segment;// 载入分词模块
var POSTAG = require('node-segment').POSTAG;// 载入词性接口
var segment = new Segment();// 创建实例
segment.useDefault();// 使用默认的识别模块及字典，载入字典文件需要1秒，仅初始化时执行一次即可

var luaUtil = (function () {

    function luaUtil() {
    }

    /**
     * 清空备用搜索 redis db
     *
     *  @author 王俊
     *  @date 2017-11-27
     *
     * @param callback
     *          error: 是否清空失败
     */
    luaUtil.clearOfflineSearchRedisDB = function (callback) {
        yjxRedisManager.getOfflineSearchRedisDBMgr(function (error, scriptMgr) {
            if(error) {
                return callback(error);
            }
            // 脚本约定, 若清空 db 成功则返回0
            scriptMgr.run('yjx_search_clear_db', [], [], function (error, result) {
                return callback(error, result);
            });
        })
    };

    /**
     * 切换线上和离线的搜索 redis db
     *
     * @author 王俊
     * @date 2017-11-27
     *
     * @param callback
     */
    luaUtil.switchSearchRedisDB = function (callback) {
        yjxRedisManager.getConfigSearchRedisDBMgr(function (error, scriptMgr) {
            if(error) {
                return callback(error, null);
            }
            // 切换 db, 约定返回切换后的线上 db 编号 1/2
            scriptMgr.run('yjx_search_switch_db', [], [], function (error, result) {
                return callback(error, result);
            });
        });
    };


    /**
     * 查询当前 redis 的缓存建立状态
     * @param callback
     */
    luaUtil.querySearchRedisStatus = function (callback) {

        yjxRedisManager.getConfigSearchRedisDBMgr(function (getMgrErr, scriptMgr) {
            if(getMgrErr) {
                return callback(getMgrErr, null);
            }

            scriptMgr.run('yjx_search_query_build_status',[], [], function (queryErr, results) {
                if(queryErr) {
                    return callback(queryErr, null);
                }
                var errCode = Number(results[0]);
                if(errCode !== 0) {
                    return callback(new Error('yjx_search_query_build_status.lua error'), null);
                }
                var retData = {
                    buildStart : results[1],
                    buildEnd : results[2]
                };
                return callback(queryErr, retData);
            });
        });
    };

    /**
     * 更新搜索的缓存建立状态
     *
     * @author 王俊
     * @date 2017-11-27
     *
     * @param force     是否强制建立
     * @param start     缓存开始时间字符串 如: 2017-11-27 11:25:46
     * @param end       缓存结束时间字符串, 同 Start
     * @param callback  回调
     *          error: 更新成功/失败
     */
    luaUtil.updateSearchRedisStatus = function (force, start, end, callback) {
        var keys = [];
        var values = [];
        force = force || 0;
        values.push(force);
        if(start) {
            values.push(start);
        }
        if(end) {
            values.push(end);
        }
        yjxRedisManager.getConfigSearchRedisDBMgr(function (getMgrErr, scriptMgr) {
            if(getMgrErr) {
                return callback(getMgrErr);
            }
            scriptMgr.run('yjx_search_update_build_status', keys, values, function (error, errCode) {
                if(error) {
                    return callback(error);
                }
                // lua 出错
                // if(Number(errCode) !== 0) {
                //     return callback(new Error('yjx_search_update_build_status.lua error'));
                // }
                return callback(error);
            });
        });
    };

    /**
     * 添加一个项目到 redis 中去
     *
     * @author 王俊
     * @date 2017-11-25
     *
     * @param uniItemInfos 统一项目信息, 需包含如下字段
     *          [{
     *              baseInfo : {}, 展示使用的原始信息
     *              kwdInfo: {},   关键字信息, 含 场景,行业, 风格, 自定义等分类标签
     *          }]
     *
     * @param callback
     */
    luaUtil.addUniItemToRedis = function (uniItemInfos, callback) {
        if(!uniItemInfos) {
            return callback(null, null);
        }
        if(uniItemInfos.length > 1) {
            console.log('\\n\\n\\n\\n同一个模板存在多个模板组526\\n\\n\\n\\n');
        }
        yjxRedisManager.getOfflineSearchRedisDBMgr(function (error, scriptMgr) {
            if(error) {
                return callback(error, null);
            }
            // 串行插入
            var tasks = [];
            for (var i=0; i<uniItemInfos.length; i++) {
                var task = (function (uniItemInfo) {
                    return function (callback) {
                        // 1. 转换数据
                        var keys = [];
                        var values = [];
                        // 1. uni_item_id，统一模版id，
                        values.push(uniItemInfo.baseInfo.id);
                        // 2. show_type_id，一级分类，
                        values.push(uniItemInfo.baseInfo.st_id);
                        // 3. keywords，关键字字符串,以半角逗号分割，形如：'蓝色,商务,名片'
                        var kwdUk = uniItemInfo.kwdInfo.unknown || [];
                        var kwdIn = uniItemInfo.kwdInfo.industry || [];
                        var kwdSc = uniItemInfo.kwdInfo.scene || [];
                        var kwdSt = uniItemInfo.kwdInfo.style || [];
                        var kwdCu = uniItemInfo.kwdInfo.custom || [];
                        var kwdTitle = luaUtil.doSegmentOfText(uniItemInfo.baseInfo.name);
                        var kwdType = luaUtil.doSegmentOfText(uniItemInfo.baseInfo.typeDesc);
                        var kwds = kwdUk.concat(kwdIn).concat(kwdSc).concat(kwdSt).concat(kwdCu).concat(kwdTitle).concat(kwdType);
                        values.push(kwds.join(','));
                        // 4. info，搜索结果字符串
                        values.push(JSON.stringify(uniItemInfo.baseInfo || {}));
                        // 5. 模板组id
                        values.push(uniItemInfo.baseInfo.set_id);
                        // 6. hot_sort，排序字段，越大越靠前
                        values.push(uniItemInfo.baseInfo.useCounts);
                        // 7. date_sort，排序字段，越大越靠前
                        var date = new moment(uniItemInfo.baseInfo.time, 'YYYY-MM-DD HH:mm:ss').unix();
                        values.push(date);
                        // 8. 排序字段
                        values.push(uniItemInfo.baseInfo.order);
                        // 9. 更新时间
                        var upDate = new moment(uniItemInfo.baseInfo.upTime, 'YYYY-MM-DD HH:mm:ss').unix();
                        values.push(upDate);

                        // 执行插入脚本
                        scriptMgr.run('yjx_search_add_uni_item', keys, values, function (error, result) {
                            if(error) {
                                return callback(error, null);
                            }
                            console.log("加入缓存成功");
                            return callback(null, null);
                        });
                    }
                })(uniItemInfos[i]);
                tasks.push(task);
            }
            async.series(tasks,function (error, data) {
                return callback(error, data);
            });
        })
    };

    /**
     * 添加所有统一商品至 redis
     *
     * @author 王俊
     * @date 2-17-11-25
     *
     * @param callback 回调
     *          err: 加入失败
     *          data: 待定
     */
    luaUtil.addAllUniItemToRedis = function (callback) {
        // 查询统一模板页数, 分页添加至 redis
        var entity = new YjxUniItemsModel();
        entity.findCountFromDB(function (error, count) {
            if(error) {
                return callback(error, null);
            }

            var pageSize = 12; // 一次添加12个
            var pageCnt = Math.floor((count-1)/pageSize)+1;
            // 本地测试只缓存一页
            //if(CONFIG.DEBUG === 1) {
            //    pageCnt = 1;
            //}

            // 添加各页数据至 redis
            var tasks = [];
            for(var i=0; i<pageCnt; i++) {
                var pageTask = (function (pageNum) {
                    return function (callback) {
                        // 查询每页数据, 添加至 redis 中
                        entity.findFromDB(function (findErr, items) {
                            if(findErr) {
                                console.log('yjx/v1/api4back/util/luaUtil.js [addAllUniItemToRedis] findErr: ' + findErr);
                                return callback(findErr, null);
                            }
                            if(!items || items.length <= 0) {
                                return callback(null, null);
                            }
                            luaUtil.addUniItemsToRedis(items,function (addErr, result) {
                                return callback(addErr, result);
                            });
                        }, pageNum*pageSize, pageSize);
                    }
                })(i);
                if(pageTask) {
                    tasks.push(pageTask);
                }
            }
            async.series(tasks, function (addErr, result) {
                if(addErr) {
                    return callback(addErr, null);
                }
                var retData = {}; // 结构待定
                return callback(null, retData);
            });
        });
    };

    /**
     * 添加一组统一项目至 redis
     *
     * @author 王俊
     * @date 2017-11-25
     *
     * @param items     统一项目行数据的数组
     * @param callback  回调
     *          err: 错误
     *          data: 待定
     */
    luaUtil.addUniItemsToRedis = function (items, callback) {
        // 循环一组统一商品, 分别取得对应信息并加入 redis
        var tasks = [];
        for (var i=0; i<items.length; i++) {
            var itemTask = (function (uniItem) {
                // ppt 暂不加入缓存
                if(Number(uniItem.item_type) === 20) {return null;}

                // 视频/设计加入缓存
                return function (callback) {
                    var itemType = Number(uniItem.item_type);
                    luaUtil.getOneUniItemInfos(uniItem.uni_item_id, itemType,function (getInfoErr, infos) {
                        // 出错暂不停止(部分数据有误, 无法取得对应信息)
                        console.log('getOneUniItemInfos complete: ' + uniItem.uni_item_id);
                        if(getInfoErr) {
                            console.log('yjx/v1/api4back/util/luaUtil.js [addUniItemsToRedis] getInfoErr: ' + getInfoErr);
                            return callback(null, null);
                        }
                        // 添加至 redis
                        luaUtil.addUniItemToRedis(infos, function (addErr, data) {
                            // 添加失败, 暂不停止
                            if(addErr) {
                                console.log('yjx/v1/api4back/util/luaUtil.js [addUniItemsToRedis] addErr: ' + addErr);
                                return callback(null, null);
                            }
                            return callback(null, data);
                        });
                    });
                }
            })(items[i]);
            if(itemTask) {
                tasks.push(itemTask);
            }
        }
        async.parallelLimit(tasks, 5, function (error, data) {
            if(error) {
                return callback(error, null);
            }
            var retData = {}; // 参数待定
            return callback(error, retData);
        });
    };

    /**
     * 获取统一项目的信息, 包括显示的基础信息
     * @param uniId
     * @param itemType
     * @param callback
     *          [{
     *              kwdInfo
     *              baseInfo
     *          }]
     */
    luaUtil.getOneUniItemInfos = function (uniId, itemType, callback) {

        var entity = new YjxUniItemsModel();

        // 1. 获取关键词相关信息
        entity.getUniItemKeywordInfo(uniId, function (getKwdErr, kwdInfo) {
            if(getKwdErr) {
                return callback(getKwdErr, null);
            }

            // 设计基础信息
            if(itemType === 10) {
                entity.getUniItemDesignBaseInfos(uniId, function (getBaseInfoErr, baseInfos) {
                    if(getBaseInfoErr || !baseInfos || baseInfos.length <=0) {
                        return callback(getBaseInfoErr || '模板不存在或已下架', null);
                    }
                    var rets = [];
                    for(var i=0; i<baseInfos.length; i++) {
                        rets.push({
                            kwdInfo : kwdInfo,
                            baseInfo : baseInfos[i]
                        })
                    }
                    return callback(null, rets);
                });
                return;
            }

            // ppt 基础信息
            if(itemType === 20) {
                entity.getUniItemPPTBaseInfos(uniId,function (getBaseInfoErr, baseInfos) {
                    if(getBaseInfoErr || !baseInfos || baseInfos.length <=0) {
                        return callback(getBaseInfoErr || '模板不存在或已下架', null);
                    }
                    var rets = [];
                    for(var i=0; i<baseInfos.length; i++) {
                        rets.push({
                            kwdInfo : kwdInfo,
                            baseInfo : baseInfos[i]
                        })
                    }
                    return callback(null, rets);
                });
                return;
            }

            // 视频基础信息
            if(itemType === 30) {
                entity.getUniItemVideoBaseInfos(uniId, function (getBaseInfoErr, baseInfos) {
                    if(getBaseInfoErr || !baseInfos || baseInfos.length <=0) {
                        return callback(getBaseInfoErr || '模板不存在或已下架', null);
                    }
                    var rets = [];
                    for(var i=0; i<baseInfos.length; i++) {
                        rets.push({
                            kwdInfo : kwdInfo,
                            baseInfo : baseInfos[i]
                        })
                    }
                    return callback(null, rets);
                });
                return;
            }
            return callback(getKwdErr, retData);
        });
    };

    /**
     * 从 redis 中搜索统一商品信息
     *
     * @author 王俊
     * @date 2017-11-27
     *
     * @param {Object} param 搜索参数列表
     * @param {Array}  [param.showTypes] 模板大分类showTypes_Id  [2,3,4]
     * @param {string} [param.keyword] 关键词                促销
     * @param {Array}  [param.setIds]  模板小分类set_Id        [17,18]
     * @param {Number} param.orderBy 排序字段   1 时间  2 次数  3 order  4 先按order排order相同用更新时间排
     * @param {Number} param.pageNum 页码       1  默认 0开始
     * @param {Number} param.pageSize 每页个数   12
     * @param {Number} [param.withTotalPage] 是否需要返回总页数  0不需要  1需要
     * @param {Number} [param.userId]  //TODO 保留参数 用户唯一标识
     * @param {Array} [param.tmplTypes] vip模板和非vip模板    0普通模板 10 vip模板   [0,10]
     * @param {Array} [param.durations] 视频时长维度    1,0-10  2,31-60 3,61-90 单位秒  [1,2,3]
     * @param {Array} [param.industrySetIds] 行业筛选
     * @param {Array} [param.sizeIds] 尺寸筛选
     *
     * @param callback      回调
     *          error: 查询失败
     *          data : {
     *              list: 查寻的结果列表
     *              totalPage : 总页数
     *          }
     */
    luaUtil.searchUniItemsFromRedis = function (param, callback) {
        yjxRedisManager.getOnlineSearchRedisDBMgr(function (getMgrErr, scriptMgr) {
            if(getMgrErr) {
                return callback(getMgrErr, null);
            }
            var keys = [];
            var values = [];
            // 1. ARGV[1]:关键词多个逗号拼接
            param.keyword = param.keyword?param.keyword:[];
            values.push(param.keyword.join(','));
            // 2. show_type_id逗号不能为空
            param.showTypes = param.showTypes?param.showTypes:[];
            values.push(param.showTypes.join(','));
            // 3. setIds 模板组 id
            param.setIds = param.setIds?param.setIds:[];
            values.push(param.setIds.join(','));
            // 4. 排序   1.按时间排(默认desc)  2.按热度排, 3. order 排序
            values.push(param.orderBy);
            // 5. pageNum 页码 0开始
            values.push(param.pageNum);
            // 6. pageSize
            values.push(param.pageSize);
            // 7. 视频模板类型
            param.tmplTypes = param.tmplTypes?param.tmplTypes:[];
            values.push(param.tmplTypes.join(','));
            // 8. 视频时长
            param.durations = param.durations?param.durations:[];
            values.push(param.durations.join(','));
            // 9. 行业
            param.industrySetIds = param.industrySetIds?param.industrySetIds:[];
            values.push(param.industrySetIds.join(','));
            // 10. 尺寸
            param.sizeIds = param.sizeIds?param.sizeIds:[90];
            values.push(param.sizeIds.join(','));
            scriptMgr.run('yjx_search_query_item', keys, values, function (queryErr, results) {
                if(queryErr || !results) {
                    return callback(queryErr || '搜索失败', null);
                }
//                var errCode = results[0];
//                if(errCode !== 0) {
//                    console.log('yjx_search_query_item lua errCode: ' + errCode);
//                    return callback(new Error('yjx_search_query_item lua error'), null);
//                }
                var retData = {
                    list : JSON.parse(results[1] || '[]')
                };
                if (param.withTotalPage) {
                    retData.totalPage = results[2];
                }
                return callback(queryErr, retData);
            });
        });
    };

    /**
     * 分词功能, 在 sundryUtil 中也有一份, 重复是为了避免 util 间相互引用
     *
     * @author 王俊
     * @date 2017-11-27
     *
     * @param txt 待分词内容
     * @param min 可分词的最小长度, 默认2
     * @param max 可分词的最大程度, 默认6
     * @return 分词结果, 字符串数组
     */
    luaUtil.doSegmentOfText = function(txt,min,max){
        if(!txt)    return null;
        // 只能2-6个字以内分词
        min = min || 2;
        max = max || 6;
        if(txt.length>max || txt.length<min){
            return [txt]
        }
        var segs = segment.doSegment(txt, {stripPunctuation: true});
        var segWords=[];
        for(var i=segs.length-1 ; i>=0;i--){
            var one = segs[i];
            if( one.p === POSTAG.D_N     // 名词 名语素
                ||one.p === POSTAG.D_S   // 处所词
                ||one.p === POSTAG.A_NR  // 人名
                ||one.p === POSTAG.A_NS  // 地名
                ||one.p === POSTAG.D_A   // 形容词 形语素
                ||one.p === POSTAG.D_Z   // 状态词
                ||one.p === POSTAG.D_V    // 动词 动语素
            ){
                // 过滤掉部分词语，例如：色
                var w = one.w.replace(/色/g,'');
                segWords.push(w);
            }
        }
        // 分词失败, 结果为空
        if(segWords.length === 0) {
            segWords.push(txt);
        }
        return segWords;
    };



    /**
     * 获取活动访问次数的实际数据
     * @author mk
     * @date 2018-5-30
     * @param actId 活动id
     * @param callback 0/1 0表示成功，1表示失败
     */
    luaUtil.getActivityCount= function (actId,callback) {
        redisManager.getApiRedisDBMgr(function (getMgrErr, scriptMgr) {
            if(getMgrErr) {
                return callback(getMgrErr);
            }
            var keys = [];
            var values = [];
            values.push(actId);
            scriptMgr.run('getActivityCount', keys, values, function (error,result) {
                return callback(error,result);
            });
        });
    };



    return luaUtil;
})();

module.exports = luaUtil;